/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include <线性代数/矢量计算.h>
#include <core/结构数据.h>

#include "core/属性.h"
#include "数学/数学.h"


vec3 f_math_向量归一化(const vec3& dirA, uint8 type) {
	switch (type) {
		case 0: {
			return vec_normalize(dirA);
		}
		default:
			break;
	}
	return vec_normalize(dirA);
}

void f_math_向量归一化m(const S_Vec3Array* dirA, S_Vec3Array* r, uint8 type) {
	uint32 num = dirA->count;

	f_core_array_resize((S_Array*)r, num);

	for (uint32 i = 0; i < num; ++i) {
		r->ptr_userData[i] = vec_normalize(dirA->ptr_userData[i]);
	}
}



float32 f_math_两向量标量(const vec3& dirA, const vec3& dirB, uint8 type) {
	switch (type) {
	case 0:
		return vec_dot(dirA, dirB);
	//case 1:
	//	return vec_len(dirA, dirB);
	}
	return 0;
}

void f_math_两向量标量m(const S_Vec3Array* dirA, const S_Vec3Array* dirB, S_F32Array* r, uint8 type) {
	uint32 num = dirA->count;

	f_core_array_resize((S_Array*)r, num);

	bool 是否单值 = dirB->count < num;

	switch (type)
	{
	case 1: {
		if (是否单值) {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = f_graph_两向量夹角弧度(dirA->ptr_userData[i], dirB->ptr_userData[0]);
			}
		}
		else {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = f_graph_两向量夹角弧度(dirA->ptr_userData[i], dirB->ptr_userData[i]);
			}
		}
	}
	case 2: {
		float32 上一个值 = 0;
		if (是否单值) {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = vec_dot(dirA->ptr_userData[i], dirB->ptr_userData[0]) + 上一个值;
				上一个值 = r->ptr_userData[i];
			}
		}
		else {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = vec_dot(dirA->ptr_userData[i], dirB->ptr_userData[i]) + 上一个值;
				上一个值 = r->ptr_userData[i];
			}
		}
	}
	default:
		if (是否单值) {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = vec_dot(dirA->ptr_userData[i], dirB->ptr_userData[0]);
			}
		}
		else {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = vec_dot(dirA->ptr_userData[i], dirB->ptr_userData[i]);
			}
		}
		break;
	}
}

vec3 f_math_两向量叉积(const vec3& dirA, const vec3& dirB) {
	return vec_cross(dirA, dirB);
}

void f_math_两向量叉积m(const S_Vec3Array* dirA, const S_Vec3Array* dirB, S_Vec3Array* r) {
	uint32 num = dirA->count;

	f_core_array_resize((S_Array*)r, num);

	bool 是否单值 = dirB->count < num;

	if (是否单值) {
		for (uint32 i = 0; i < num; ++i) {
			r->ptr_userData[i] = vec_cross(dirA->ptr_userData[i], dirB->ptr_userData[0]);
		}
	}
	else {
		for (uint32 i = 0; i < num; ++i) {
			r->ptr_userData[i] = vec_cross(dirA->ptr_userData[i], dirB->ptr_userData[i]);
		}
	}
}

void f_math_向量长度m(S_F32Array* r, const S_Vec3Array* dirA, uint8 type) {
	uint32 num = dirA->count;
	f_core_array_resize((S_Array*)r, num);

	switch (type) {
		case 0: {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = vec_len(dirA->ptr_userData[i]);
			}
			break;
		}
		case 1: {
			vec3 上一个点坐标 = {};
			float32 上一个点距离 = 0;
			for (uint32 i = 0; i < num; ++i) {
				float32 cl = vec_len(dirA->ptr_userData[i] - 上一个点坐标);
				上一个点距离 += cl;
				r->ptr_userData[i] = 上一个点距离;
				上一个点坐标 = dirA->ptr_userData[i];
			}
			break;
		}
		case 2: {
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] = dot({0.2125, 0.7154, 0.0721}, dirA->ptr_userData[i]);
			}
			break;
		}
		case 3: {
			float32 最小长度 = FLT_MAX;
			for (uint32 i = 0; i < num; ++i) {
				float32 cl = vec_len(dirA->ptr_userData[i]);
				if(cl < 最小长度) 最小长度 = cl;

				r->ptr_userData[i] = cl;
			}
			for (uint32 i = 0; i < num; ++i) {
				r->ptr_userData[i] -= 最小长度;
			}
			break;
		}
	default:
		for (uint32 i = 0; i < num; ++i) {
			r->ptr_userData[i] = vec_len(dirA->ptr_userData[i]);
		}
		break;
	}
}



vec3 f_mat_点统计v3(const S_Vec3Array* point, const S_Props* 计算方式) {
	vec3 中心 = {};
	switch (f_prop_enum(*计算方式)) {
		case 0: {
			for (uint32 i = 0; i < point->count; ++i) {
				中心 += point->ptr_userData[i];
			}
			中心 /= point->count;
			break;
		}

		case 1: {
			vec3 最小 = { 2000000000, 2000000000, 2000000000 };
			vec3 最大 = { -2000000000, -2000000000, -2000000000 };
			for (uint32 i = 0; i < point->count; ++i) {
				最小 = vec_Min(最小, point->ptr_userData[i]);
				最大 = vec_Max(最大, point->ptr_userData[i]);
			}
			中心 = (最大 - 最小) * 0.5 + 最小;
			break;
		}
		default:
			break;
	}
	
	return 中心;
}

vec2 f_mat_点统计v2(const S_Vec2Array* point, const S_Props* 计算方式) {
	vec2 中心 = {};
	switch (f_prop_enum(*计算方式)) {
		case 0: {
			for (uint32 i = 0; i < point->count; ++i) {
				中心 += point->ptr_userData[i];
			}
			中心 /= point->count;
			break;
		}

		case 1: {
			vec2 最小 = { 2000000000, 2000000000 };
			vec2 最大 = { -2000000000, -2000000000 };
			for (uint32 i = 0; i < point->count; ++i) {
				最小 = vec_Min(最小, point->ptr_userData[i]);
				最大 = vec_Max(最大, point->ptr_userData[i]);
			}
			中心 = (最大 - 最小) * 0.5 + 最小;
			break;
		}
		default:
			break;
	}

	return 中心;
}

void f_math_Cube相机矩阵(vec3 pos, Mat44f mat[6]) {
	//pos = -pos;

	mat[0] = f_mat44_构建XYZ变换矩阵({ pos, {0,-90,0}, {-1,-1,1} });		//ok
	mat[1] = f_mat44_构建XYZ变换矩阵({ pos, {0,90,0}, {-1,-1,1} });			//ok
	
	mat[2] = f_mat44_构建XYZ变换矩阵({ pos, {-90,0,0}, {1,-1,-1} });		//ok
	mat[3] = f_mat44_构建XYZ变换矩阵({ pos, {90,0,0}, {1,-1,-1} });			//ok
	
	mat[5] = f_mat44_构建XYZ变换矩阵({ pos, {0,180,180}, {-1, 1, -1} });	//ok
	mat[4] = f_mat44_构建XYZ变换矩阵({ pos, {0,180,0}, {-1, -1, 1} });		//ok

	//mat[0] = f_mat44_构建XYZ变换矩阵({ pos, {0,90,0}, {1,-1,1} });
	//mat[1] = f_mat44_构建XYZ变换矩阵({ pos, {0,0,0}, {1,-1,1} });
	//mat[2] = f_mat44_构建XYZ变换矩阵({ pos, {0,0,0}, {1,-1,1} });
	//mat[3] = f_mat44_构建XYZ变换矩阵({ pos, {0,0,0}, {1,-1,1} });
	//mat[4] = f_mat44_构建XYZ变换矩阵({ pos, {0,0,0}, {1,-1,1} });
	//mat[5] = f_mat44_构建XYZ变换矩阵({ pos, {0,0,0}, {1, -1,1} });

	//mat[0] = f_mat44_LookAtMatrix(pos, pos + vec3{ 1,0,0 }, { 0,1,0 });
	//mat[1] = f_mat44_LookAtMatrix(pos, pos + vec3{ -1,0,0}, {0,1,0});
	//mat[2] = f_mat44_LookAtMatrix(pos, pos + vec3{ 0,1,0 }, { 0,1,0 });
	//mat[3] = f_mat44_LookAtMatrix(pos, pos + vec3{ 0,-1,0 }, { 0,1,0 });
	//mat[4] = f_mat44_LookAtMatrix(pos, pos + vec3{ 0,0,1 }, { 0,1,0 });
	//mat[5] = f_mat44_LookAtMatrix(pos, pos + vec3{ 0,0,-1 }, { 0,1,0 });

	for (uint32 i = 0; i < 6; ++i) {
		mat[i] = f_mat44_Invert(mat[i]);
	}




	//// 计算距离
	//float calculateDistance(float height, float fovYDegrees) {
	//	float fovYRadians = degToRad(fovYDegrees);
	//	float tanHalfFovY = tan(fovYRadians / 2);
	//	return height / (2.0f * tanHalfFovY);
	//}

}




